package cn.itcast.tanhua.quanziesapplication.api.impl;

import cn.itcast.tanhua.mytanhuadubbointerface.api.QuanziSearchApi;
import cn.itcast.tanhua.vo.PageResult;
import cn.itcast.tanhua.vo.QuanZiVo;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author 郭文亮
 * @since 2021/12/6 17:13
 */
@Service
public class QuanziSearchApiImpl implements QuanziSearchApi {

    @Autowired
    private RestHighLevelClient client;

    @PostConstruct
    public void initIndex() throws Exception {
        IndicesClient indices = this.client.indices();

        // 先查询是否存在索引
        GetIndexRequest getIndexRequest=new GetIndexRequest("quanzi");
        boolean exists = indices.exists(getIndexRequest, RequestOptions.DEFAULT);
        if (!exists) {
            // 如果索引不存在，则创建索引和对应的映射
            CreateIndexRequest createIndexRequest = new CreateIndexRequest("quanzi");
            String mapping = "{\n" +
                    "  \"properties\": {\n" +
                    "          \"textContent\": {\n" +
                    "            \"type\": \"text\"\n" +
                    "          },\n" +
                    "          \"nickname\": {\n" +
                    "            \"type\": \"text\"\n" +
                    "          }\n" +
                    "        }\n" +
                    "}";
            createIndexRequest.mapping(mapping, XContentType.JSON);
            indices.create(createIndexRequest, RequestOptions.DEFAULT);
        }
    }

    @Override
    public boolean synchroEsData(List<QuanZiVo> quanziList) throws Exception {
        try {
            BulkRequest bulkRequest = new BulkRequest();
            for (QuanZiVo quanZiVo : quanziList) {
                String data = JSON.toJSONString(quanZiVo);
                IndexRequest indexRequest = new IndexRequest("quanzi").source(data, XContentType.JSON);
                // 添加进bulk
                bulkRequest.add(indexRequest);
            }
            this.client.bulk(bulkRequest, RequestOptions.DEFAULT);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public PageResult queryQuanziByKeyword(Integer page, Integer pageSize, String keyword) throws Exception {
        // 2指定索引库
        SearchRequest searchRequest = new SearchRequest("quanzi");
        // 4创建构造器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 6构建boolQuery
        BoolQueryBuilder query = QueryBuilders.boolQuery();

        // 关键字查询
        QueryStringQueryBuilder queryKeyword = QueryBuilders.queryStringQuery(keyword).field("nickname").field("textContent").defaultOperator(Operator.AND);
        query.must(queryKeyword);

        // 5.指定查询条件，使用boolQuery
        sourceBuilder.query(query);

        // 设置高亮
        HighlightBuilder highlighter = new HighlightBuilder();
        // 设置三要素
        highlighter.field("textContent");
        highlighter.preTags("<em color='red'>");
        highlighter.postTags("</em>");
        sourceBuilder.highlighter(highlighter);

        // 显示从第0条开始，显示50条
        sourceBuilder.from((page-1)*pageSize);
        sourceBuilder.size(pageSize);

        // 按照点赞数排序
        sourceBuilder.sort("likeCount", SortOrder.DESC);
        // 5指定查询方式
        sourceBuilder.query(query);

        // 3创建构造器
        searchRequest.source(sourceBuilder);
        // 1指定查询
        SearchResponse response = this.client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits searchHits = response.getHits();
        // 查询到的条数
        long quanziTotal = searchHits.getTotalHits().value;
        // 查询的结果
        SearchHit[] hits = searchHits.getHits();
        List<QuanZiVo> quanZiVoList = new ArrayList<>();
        for (SearchHit hit : hits) {
            // 将查询到的数据装换为Json字符串
            String sourceAsString = hit.getSourceAsString();
            QuanZiVo quanZiVo = JSON.parseObject(sourceAsString, QuanZiVo.class);
            // 获取高亮结果，替换quanZiVo中的textContent
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField HighlightField = highlightFields.get("textContent");
            Text[] fragments = HighlightField.fragments();
            //highlight title替换 替换goods中的title
            quanZiVo.setTextContent(fragments[0].toString());
            quanZiVoList.add(quanZiVo);
        }
        PageResult pageResult = new PageResult();
        pageResult.setPage(page);
        pageResult.setPagesize(pageSize);
        pageResult.setItems(quanZiVoList);
        pageResult.setCounts((int)quanziTotal);
        return pageResult;
    }
}
